
#ifndef __M_MATCH_H__
#define __M_MATCH_H__
// 游戏匹配模块

#include "room.hpp"
#include <list>
#include <condition_variable>
#include <thread>

// 玩家匹配队列
template <class T>
class match_queue
{
public:
    size_t size()
    {
        std::unique_lock<std::mutex> lock(_mutex);
        return _match.size();
    }
    bool empty()
    {
        std::unique_lock<std::mutex> lock(_mutex);
        return _match.empty();
    }
    void remove(const T &data)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _match.remove(data);
    }
    void wait()
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _cond.wait(lock);
    }
    void push(const T &data)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _match.push_back(data);
        _cond.notify_all();
    }
    bool pop(T &data)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        if (_match.empty())
            return false;
        data = _match.front();
        _match.pop_front();
        return true;
    }

private:
    std::mutex _mutex;
    std::condition_variable _cond;
    std::list<T> _match;
};

class matchManager
{
public:
    matchManager(online_user *online, user_table *us_tb, roomManager *room)
        : _online(online), _us_tb(us_tb), _room(room),
        _match_normal(std::thread(std::bind(&matchManager::entry_noraml,this))),
        _match_large(std::thread(std::bind(&matchManager::entry_large,this))),
        _match_super(std::thread(std::bind(&matchManager::entry_super,this)))
    {
        DLOG("匹配模块初始化完成");
    }

    //匹配功能,将用户的id添加到一个匹配队列中
    bool add(uint64_t uid)
    {
        //获取用户的信息
        Json::Value user;
        bool ret=_us_tb->select_by_id(uid,user);
        if(ret==false)
        {
            DLOG("%ld:用户信息不存在",uid);
            return false;
        }
        int score=user["score"].asInt();
        //添加到指定队列中
        if(score<2000)
        {
            _normal_queue.push(uid);
        }
        else if(score>=2000&&score<3000)
        {
            _large_queue.push(uid);
        }
        else
        {
            _super_queue.push(uid);
        }
        return true;
    }
    //退出匹配功能,将用户的id从匹配队列中移除
    bool del(uint64_t uid)
    {   
        //获取用户的信息
        Json::Value user;
        bool ret=_us_tb->select_by_id(uid,user);
        if(ret==false)
        {
            DLOG("%ld:用户信息不存在",uid);
            return false;
        }
        int score=user["score"].asInt();
        //从指定队列移除
        if(score<2000)
        {
            _normal_queue.remove(uid);
        }
        else if(score>=2000&&score<3000)
        {
            _large_queue.remove(uid);
        }
        else
        {
            _super_queue.remove(uid);
        }
        return true;
    }
private:
    void handle_match(match_queue<uint64_t>& match)
    {
        while(1)
        {
            while(match.size()<2)
            {
                match.wait();
            }
            //1,队列中人数超过两个,出队两个玩家进行游戏
            uint64_t uid1,uid2;
            bool ret=match.pop(uid1);
            if(ret==false){continue;}
            ret=match.pop(uid2);
            if(ret==false){this->add(uid1);continue;}

            //2,检查这两个玩家是否在线
            wsserver_t::connection_ptr conn1=_online->get_conn_from_hall(uid1);
            if(conn1.get()==nullptr)
            {
                this->add(uid2);
                continue;
            }
            wsserver_t::connection_ptr conn2=_online->get_conn_from_hall(uid2);
            if(conn2.get()==nullptr)
            {
                this->add(uid1);
                continue;
            }   
            //3,创建房间
            room::ptr rp=_room->createRoom(uid1,uid2);
            if(rp.get()==nullptr)
            {
                this->add(uid1);
                this->add(uid2);
                continue;
            }

            //4,向这两个玩家发送匹配成功响应
            Json::Value resp;
            resp["optype"]="match_success";
            resp["reslut"]=true;
            std::string body;
            Json_util::seralize(resp,body);

            conn1->send(body);
            conn2->send(body);
        }
    }
    void entry_noraml(){return handle_match(_normal_queue);}
    void entry_large(){return handle_match(_large_queue);}
    void entry_super(){return handle_match(_super_queue);}
private:
    match_queue<uint64_t> _normal_queue;
    match_queue<uint64_t> _large_queue;
    match_queue<uint64_t> _super_queue;
    online_user *_online; // 在线用户管理
    user_table *_us_tb;   // 用户信息管理
    roomManager *_room;   // 房间管理
    std::thread _match_normal;
    std::thread _match_large;
    std::thread _match_super;
};

#endif